package it.unisannio.lesim.fsm;

import it.unisannio.lesim.fsm.exception.UnrecognizedTokenException;
import it.unisannio.lesim.fsm.exception.UnrecognizedExpressionException;
import java.util.Hashtable;
import java.util.Map;

/**
 *
 * @author Marco Calisti
 * @author Antonio Cuomo
 * @author Rocco Mazzeo
 * @author Francesco Pacilio
 * 
 */
class ActionPerformer {

    ActionTokenizer scanner;
    Map fieldsToValues;
    Map storage;
    String messageKind;
    long time;
    long messageTime;
    void performAction(String action, Map storage, String typeMessage, Hashtable fields, long time, long messageTime) throws UnrecognizedExpressionException {
        this.scanner = new ActionTokenizer(action);
        this.fieldsToValues = fields;
        this.storage = storage;
        this.messageKind = typeMessage;
        this.time = time;
        this.messageTime=messageTime;
        evalActionExp();
        return;
    }

    private void evalSingleAction() throws UnrecognizedExpressionException {
        try {
            scanner.consumeToken();
            if (scanner.lastTokenType() == ActionTokenizer.SAVE_FIELD_COMMAND) {
                scanner.consumeToken();
                if (scanner.lastTokenType() != ActionTokenizer.LEFT_SQUARE_PAR) {
                    throw new UnrecognizedExpressionException();
                }
                scanner.consumeToken();
                if (scanner.lastTokenType() != ActionTokenizer.STRING) {
                    throw new UnrecognizedExpressionException();
                }
                String varName = scanner.lastLexeme();
                scanner.consumeToken();
                if (scanner.lastTokenType() != ActionTokenizer.STRING_SEPARATOR) {
                    throw new UnrecognizedExpressionException();
                }
                scanner.consumeToken();
                if (scanner.lastTokenType() != ActionTokenizer.STRING) {
                    throw new UnrecognizedExpressionException();
                }
                String fieldName = scanner.lastLexeme();
                scanner.consumeToken();
                if (scanner.lastTokenType() != ActionTokenizer.RIGHT_SQUARE_PAR) {
                    throw new UnrecognizedExpressionException();
                }
                FieldValue value = (FieldValue) fieldsToValues.get(fieldName);
                storage.put(varName, value.getValue());
            } 
            else if (scanner.lastTokenType() == ActionTokenizer.SAVE_TIME_COMMAND) {
                scanner.consumeToken();
                if (scanner.lastTokenType() != ActionTokenizer.LEFT_SQUARE_PAR) {
                    throw new UnrecognizedExpressionException();
                }
                scanner.consumeToken();
                if (scanner.lastTokenType() != ActionTokenizer.STRING) {
                    throw new UnrecognizedExpressionException();
                }
                String varName = scanner.lastLexeme();
                scanner.consumeToken();
                if (scanner.lastTokenType() != ActionTokenizer.RIGHT_SQUARE_PAR) {
                    throw new UnrecognizedExpressionException();
                }
                storage.put(varName, Long.toString(messageTime));
            } 
            else {
                throw new UnrecognizedExpressionException();
            }
        } catch (UnrecognizedTokenException ex) {
            throw new UnrecognizedExpressionException();
        }
    }

    private void evalActionExp() throws UnrecognizedExpressionException {
        try {
            evalSingleAction();
            scanner.consumeToken();
            if (scanner.lastTokenType() == ActionTokenizer.END_REACHED) {
                return;
            } else if (scanner.lastTokenType() == ActionTokenizer.COMMAND_SEPARATOR) {
                evalActionExp();
            } else {
                throw new UnrecognizedExpressionException();
            }
        } catch (UnrecognizedTokenException ex) {
            throw new UnrecognizedExpressionException();
        }
    }
}
